﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;

namespace Common.Util
{
    /// <summary>
    /// 队列处理抽象类
    /// </summary>
    public abstract class AbstractTaskProcessor<T>
    {
        private static log4net.ILog _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        protected readonly Queue<T> _queue = new Queue<T>();
        protected Thread _processThread = null;
        protected bool _bRunning = false;
        protected object _lockRunning = new object();

        public void Start()
        {
            lock (_lockRunning)
            {
                _logger.Debug("AbstractTaskProcessor Started");

                _bRunning = true;

                _processThread = new Thread(new ThreadStart(Run));
                _processThread.Start();
            }
        }

        public void Stop()
        {
            lock (_lockRunning)
            {
                if (_processThread != null)
                {
                    _logger.Debug("AbstractTaskProcessor Stopped");

                    _bRunning = false;
                    _processThread.Abort();
                    _processThread = null;
                }
            }
        }

        public bool IsRunning()
        {
            lock (_lockRunning)
            {
                return _bRunning;
            }
        }
        
        public void AddTask(T task)
        {
            lock (_queue)
            {
                _queue.Enqueue(task);
                Monitor.PulseAll(_queue);
                _logger.Debug("AbstractTaskProcessor AddTask[" + task.ToString() + "]");
            }
        }

        protected T RemoveTask()
        {
            lock (_queue)
            {
                while (_queue.Count == 0)
                {
                    Monitor.Wait(_queue);
                }
                T task = _queue.Dequeue();
                Monitor.PulseAll(_queue);

                _logger.Debug("AbstractTaskProcessor RemoveTask[" + task.ToString() + "]");

                return task;
            }
        }

        protected abstract void Process(T task);

        private void Run()
        {
            while (_bRunning)
            {
                T task = RemoveTask();

                try
                {
                    Process(task);
                }
                catch (Exception e)
                {
                    _logger.Error("AbstractTaskProcessor Task[" + task.ToString() + "] " + e);
                }
            }
        }
    }
}
